package com.yupi.springbootinit.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.springbootinit.mapper.PrintingRecordMapper;
import com.yupi.springbootinit.model.dto.production.printingrecord.PrintingRecordAddRequest;
import com.yupi.springbootinit.model.dto.production.printingrecord.PrintingRecordQueryRequest;
import com.yupi.springbootinit.model.dto.production.printingrecord.PrintingRecordUpdateRequest;
import com.yupi.springbootinit.model.entity.PrintingRecord;
import com.yupi.springbootinit.model.vo.production.PrintingRecordVO;
import com.yupi.springbootinit.service.PrintingRecordService;
import com.yupi.springbootinit.service.ProcessBatchService;
import com.yupi.springbootinit.service.ProcessSheetService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 打印机台记录服务实现
 */
@Service
@Slf4j
public class PrintingRecordServiceImpl extends ServiceImpl<PrintingRecordMapper, PrintingRecord>
        implements PrintingRecordService {

    @Resource
    private ProcessSheetService processSheetService;

    @Resource
    private ProcessBatchService processBatchService;

    @Override
    public Long addPrintingRecord(PrintingRecordAddRequest addRequest) {
        if (addRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }

        // 参数校验
        validateAddParams(addRequest);

        PrintingRecord record = new PrintingRecord();
        BeanUtils.copyProperties(addRequest, record);

        // 自动计算工时
        fillDuration(record);

        // 🔧 如果没有指定流程卡号，根据产品名称自动查询工艺单号
        if (StringUtils.isNotBlank(addRequest.getProductName()) &&
                StringUtils.isBlank(addRequest.getRecordNo())) {
            Map<String, Object> processSheetInfo = processSheetService.queryProcessSheetByProductName(
                    addRequest.getProductName()
            );

            // 从查询结果中获取工艺单号作为流程卡号
            String processSheetNo = (String) processSheetInfo.get("processSheetNo");
            if (StringUtils.isNotBlank(processSheetNo)) {
                record.setRecordNo(processSheetNo);
            }
        }

        // 保存记录
        boolean result = this.save(record);
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "添加记录失败");
        }

        // 🔧 如果流程卡号仍为空，则生成默认编号
        if (StringUtils.isBlank(record.getRecordNo())) {
            String recordNo = genRecordNo(record.getId());
            record.setRecordNo(recordNo);
            this.updateById(record);
        }

        return record.getId();
    }

    @Override
    public Boolean updatePrintingRecord(PrintingRecordUpdateRequest updateRequest) {
        if (updateRequest == null || updateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数错误");
        }

        // 检查记录是否存在
        PrintingRecord oldRecord = this.getById(updateRequest.getId());
        if (oldRecord == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "记录不存在");
        }

        PrintingRecord record = new PrintingRecord();
        BeanUtils.copyProperties(updateRequest, record);

        // 自动计算工时
        fillDuration(record);

        // 数据校验
        validateRecord(record);

        boolean result = this.updateById(record);
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "更新记录失败");
        }

        return true;
    }

    @Override
    public Boolean deletePrintingRecord(Long id) {
        if (id == null || id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "记录ID错误");
        }

        // 检查记录是否存在
        PrintingRecord record = this.getById(id);
        if (record == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "记录不存在");
        }

        boolean result = this.removeById(id);
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "删除记录失败");
        }

        return true;
    }

    @Override
    public PrintingRecordVO getPrintingRecordVO(Long id) {
        if (id == null || id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "记录ID错误");
        }

        PrintingRecord record = this.getById(id);
        if (record == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "记录不存在");
        }

        return entityToVO(record);
    }

    @Override
    public Page<PrintingRecordVO> listPrintingRecordByPage(PrintingRecordQueryRequest queryRequest) {
        if (queryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "查询参数为空");
        }

        long current = queryRequest.getCurrent();
        long pageSize = queryRequest.getPageSize();

        // 🔧 构建查询条件（使用 QueryWrapper，与模板保持一致）
        QueryWrapper<PrintingRecord> queryWrapper = new QueryWrapper<>();

        if (queryRequest.getId() != null) {
            queryWrapper.eq("id", queryRequest.getId());
        }
        if (StringUtils.isNotBlank(queryRequest.getProductName())) {
            queryWrapper.like("product_name", queryRequest.getProductName());
        }
        if (StringUtils.isNotBlank(queryRequest.getDeviceName())) {
            queryWrapper.eq("device_name", queryRequest.getDeviceName());
        }
        if (queryRequest.getStartTimeBegin() != null) {
            queryWrapper.ge("start_time", queryRequest.getStartTimeBegin());
        }
        if (queryRequest.getStartTimeEnd() != null) {
            queryWrapper.le("start_time", queryRequest.getStartTimeEnd());
        }

        // 排序
        String sortField = queryRequest.getSortField();
        String sortOrder = queryRequest.getSortOrder();

        if (StringUtils.isNotBlank(sortField)) {
            // 驼峰转下划线
            String column = camelToUnderscore(sortField);
            if ("asc".equalsIgnoreCase(sortOrder)) {
                queryWrapper.orderByAsc(column);
            } else {
                queryWrapper.orderByDesc(column);
            }
        } else {
            // 默认按创建时间倒序
            queryWrapper.orderByDesc("create_time");
        }

        // 分页查询
        Page<PrintingRecord> page = this.page(new Page<>(current, pageSize), queryWrapper);

        // 🔧 转换为 VO（不需要额外的关联查询）
        Page<PrintingRecordVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(
                page.getRecords().stream()
                        .map(this::entityToVO)
                        .collect(Collectors.toList())
        );

        return voPage;
    }

    @Override
    public Map<String, Object> queryOrderByProductName(String productName) {
        if (StringUtils.isBlank(productName)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "产品名称不能为空");
        }

        // 🔧 委托给 ProcessSheetService 查询
        return processSheetService.queryProcessSheetByProductName(productName);
    }

    @Override
    public Map<String, Object> queryByFlowNumber(String flowNumber) {
        if (StringUtils.isBlank(flowNumber)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "流程卡号不能为空");
        }

        // 委托给 ProcessBatchService 查询
        return processBatchService.getByFlowNumber(flowNumber);
    }

    /**
     * 自动计算工时（分钟）
     */
    private void fillDuration(PrintingRecord record) {
        if (record.getDurationMinutes() == null
                && record.getStartTime() != null
                && record.getEndTime() != null) {
            long minutes = Duration.between(record.getStartTime(), record.getEndTime()).toMinutes();
            record.setDurationMinutes((int) Math.max(0, minutes));
        }
    }

    /**
     * 数据校验
     */
    private void validateRecord(PrintingRecord record) {
        // 时间校验
        if (record.getEndTime() != null
                && record.getStartTime() != null
                && record.getEndTime().isBefore(record.getStartTime())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "打印结束时间不得早于开始时间");
        }

        // 数量校验
        if (record.getPrintQty() != null && record.getPrintQty() < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "打印数量不能为负");
        }
        if (record.getScrapQty() != null && record.getScrapQty() < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "报废数量不能为负");
        }
    }

    /**
     * 新增参数校验
     */
    private void validateAddParams(PrintingRecordAddRequest addRequest) {
        if (StringUtils.isBlank(addRequest.getProductName())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "产品名称不能为空");
        }
        if (StringUtils.isBlank(addRequest.getUnloadOperatorName())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "下机操作人不能为空");
        }
        if (addRequest.getStartTime() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "开始时间不能为空");
        }
        if (addRequest.getEndTime() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "结束时间不能为空");
        }
        if (addRequest.getPrintQty() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "打印数量不能为空");
        }

        // 时间逻辑校验
        if (addRequest.getEndTime().isBefore(addRequest.getStartTime())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "结束时间不得早于开始时间");
        }
    }

    /**
     * 生成记录单号
     */
    private String genRecordNo(Long id) {
        String date = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE); // yyyyMMdd
        return "PR" + date + String.format("%06d", Math.abs(id % 1_000_000));
    }

    /**
     * 🔧 实体转 VO（直接复制属性，不需要关联查询）
     * processSheetNo 已经存储在 recordNo 字段中
     */
    private PrintingRecordVO entityToVO(PrintingRecord record) {
        if (record == null) {
            return null;
        }

        PrintingRecordVO vo = new PrintingRecordVO();
        BeanUtils.copyProperties(record, vo);

        // 🔧 将 recordNo 作为 processSheetNo 返回
        vo.setProcessSheetNo(record.getRecordNo());

        return vo;
    }

    /**
     * 驼峰转下划线
     */
    private String camelToUnderscore(String camelCase) {
        if (StringUtils.isBlank(camelCase)) {
            return camelCase;
        }
        return camelCase.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
    }
}